package com.ms.service.module.commonsettings;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.simple.JSONObject;

import com.ms.game.db.util.Utility;
import com.ms.service.error.ErrorCode;
import com.xpec.c4.game.utility.GUID;
import com.xpec.c4.message.MessageTypes;
import com.xpec.c4.service.group.transportlayer.GroupMessage;
import com.xpec.c4.service.message.MessageAction;
import com.xpec.c4.service.module.common.PlayerCommonInfoManager;


/**
 * 底下成員是所有共用設定的class，每種設定自行管理資訊內容<br>
 * 啟動時會以MessageTypes.S_SERVER_SYNC_INFOS來同步所有module設定<br>
 * 更新時以MessageTypes.S_UPDATE_COMMON_SETTINGS_TO_SERVERS來更新給所有module
 *
 */
public class CommonSettings {
	
	private static final Log log = LogFactory.getLog(CommonSettings.class);

	//=====================================================
	//	1. 新增的每個class都要在codec註冊
	//  2. 給予預設設定方法setDefaultSettings()
	//	3. 給予從DB讀取時轉換的方法loadAllSettingsFromDB()
	//	4. 給予getSettingByType(CommonSettingType type)獲得資訊的方法
	//	5. 要提供給GMTOOL成員名稱與對應的updateID來修改設定
	//  6. 要提供給平台的資訊在convertToWebInfo()加
	
	/**虛寶交易設定*/
	private CommonSendGiftSetting sendGiftSetting;
	
	/**重複名稱設定*/
	private CommonDoubleNameSetting doubleNameSetting;
	
	/**阻擋ip登入設定*/
	private CommonAccountLoginBlockIPSetting accountLoginBlockIPSetting;
	
	/**儲值金額限制*/
	private CommonPurchaseLimitSetting purchaseLimitSetting;
	
	/** 每日登入送東西設定 */
	private CommonSendItemSetting sendItemSetting;

	//=====================================================

	/**
	 * 預設設定
	 */
	public void setDefaultSettings(){
		this.sendGiftSetting = (CommonSendGiftSetting) CommonSettingType.SEND_GIFT.getDefaultSetting();
		this.doubleNameSetting = (CommonDoubleNameSetting) CommonSettingType.DOUBLE_NAME_CHECK.getDefaultSetting();
		this.accountLoginBlockIPSetting = (CommonAccountLoginBlockIPSetting) CommonSettingType.ACCOUNT_LOGIN_BLOCK_IP.getDefaultSetting();
		this.purchaseLimitSetting = (CommonPurchaseLimitSetting) CommonSettingType.PURCHASE_LIMIT.getDefaultSetting();
		this.sendItemSetting = (CommonSendItemSetting) CommonSettingType.SEND_ITEM.getDefaultSetting();
	
	}
	
	/**
	 * 根據type回傳設定
	 */
	public Object getSettingByType(CommonSettingType type){
		switch (type) {
			case SEND_GIFT:{
				return this.sendGiftSetting;
			}
			
			case DOUBLE_NAME_CHECK:{
				return this.doubleNameSetting;
			}
			
			case ACCOUNT_LOGIN_BLOCK_IP:{
				return this.accountLoginBlockIPSetting;
			}

			case PURCHASE_LIMIT:{
				return this.purchaseLimitSetting;
			}
			
			case SEND_ITEM:{
				return this.sendItemSetting;
			}

			//如果沒在這case判斷內的都回傳null
			default:
				return null;
		}
	}
	
	/**
	 * 讀取共用設定
	 */
	public static CommonSettings loadAllSettingsFromDB(){
		//從DB讀取
		List<CommonSettingsModel> allModels = CommonSettingsDAO.loadAllSettings();

		//載出結果
		CommonSettings commonSettings = new CommonSettings();
		
		//先將預設值套入
		commonSettings.setDefaultSettings();
		
		//用來檢查DB尚未存在的type
		ArrayList<CommonSettingType> checkList = new ArrayList<CommonSettingType>();
		
		//依照各個DB設定去覆蓋設定值
		for(CommonSettingsModel model : allModels){
			
			CommonSettingType type = model.getSettingType();
			
			if(checkList.contains(type)){
				//理論上不會進入這邊，因為model使用type當作ID
				if(log.isErrorEnabled()){
					log.error("duplicate common setting type!");
				}
				continue;
			}
			else{
				checkList.add(type);
			}
			
			try {
				
				Object object = type.getClassFromJson(model.getSettingContent());
				
				switch (type) {
				case SEND_GIFT:{
					commonSettings.sendGiftSetting = (CommonSendGiftSetting) object;
					break;
				}
				
				case DOUBLE_NAME_CHECK:{
					commonSettings.doubleNameSetting = (CommonDoubleNameSetting) object;
					break;
				}
				
				case ACCOUNT_LOGIN_BLOCK_IP:{
					commonSettings.accountLoginBlockIPSetting = (CommonAccountLoginBlockIPSetting)object;
					break;
				}
				
				case PURCHASE_LIMIT:{
					commonSettings.purchaseLimitSetting = (CommonPurchaseLimitSetting)object;
					break;
				}
				
				case SEND_ITEM:{
					commonSettings.sendItemSetting = (CommonSendItemSetting)object;
					break;
				}

				default:
					break;
				}
				
			} catch (Exception e) {
				if(log.isErrorEnabled()){
					log.error("something wrong at convert json to class, CommonSettingType:"+type, e);
				}
				continue;
			}
		}
		
		for(CommonSettingType type : CommonSettingType.values()){
			if(!checkList.contains(type)){
				if(log.isWarnEnabled()){
					log.warn("["+type.name()+"] can't find setting in DB, use default setting instead");
				}
			}
		}
		
		return commonSettings;
	}
	
	/**
	 * 根據updateID取得設定
	 */
	public Object getSetting(CommonSettingType type, int updateID){
		Object setting = getSettingByType(type);
		if(setting == null)
			return null;
		
		Field[] fields = Utility.getAllFieldToCache(type.getConvertClass());
		int index = -1;
		for(int id = 0; id < type.getUpdateID().length; id++){
			if(type.getUpdateID()[id] == updateID){
				index = id;
				break;
			}
		}
		
		if(index != -1){
			return Utility.getField(setting, fields[index]);
		}
		else{
			return null;
		}
	}
	
	/**
	 * 將異動傳給所有server和client<br>
	 * isSendToAllClient, updateIDs 都是傳給client需要填入的參數，如果updateIDs是null代表全部更新給client<br>
	 * server目前都是將整個commonSettings置換
	 */
	public static void broadcastToServersAndClients(CommonSettings commonSettings, boolean isSendToAllClient, int[] updateIDs){
		//告訴server更新
		GroupMessage msg = new GroupMessage();
		msg.setDestModuleID(null);
		msg.setMessageType(MessageTypes.S_UPDATE_COMMON_SETTINGS_TO_SERVERS);
		msg.setMessageContent(commonSettings);
		MessageAction.sendMessage(msg);
		
		//告訴client更新
		if(isSendToAllClient){
			SUpdateCommonSettingsMessage message = new SUpdateCommonSettingsMessage();
			message.setErrorCode(ErrorCode.SUCCESS);
			message.setUpdateSettings(convertCommonSettingsToUpdateSettings(commonSettings, updateIDs));
			//所有在線玩家
			List<GUID> onlineSessions = PlayerCommonInfoManager.getInstance().getOnlinePlayersSessions();
			MessageAction.sendMessage(onlineSessions, MessageTypes.S_UPDATE_COMMON_SETTINGS_TO_CLIENTS, message);
		}
	}
	
	/**
	 * 以更新的格式傳給client所有設定
	 */
	public static void sendToClientAllSettings(CommonSettings commonSettings, GUID sessionID){
		SUpdateCommonSettingsMessage message = new SUpdateCommonSettingsMessage();
		
		if(commonSettings != null){
			message.setErrorCode(ErrorCode.SUCCESS);
			message.setUpdateSettings(convertCommonSettingsToUpdateSettings(commonSettings, null));
		}
		else{
			message.setErrorCode(ErrorCode.DATA_NOT_FOUND);
		}

		MessageAction.sendMessage(sessionID, MessageTypes.S_GET_COMMON_SETTINGS_RESPONSE, message);
	}
	
	/**
	 * 把共用設定轉成給client的形式
	 */
	private static HashMap<Integer, String> convertCommonSettingsToUpdateSettings(CommonSettings commonSettings, int[] updateIDs){
		HashMap<Integer, String> result = new HashMap<Integer, String>();
		
		if(commonSettings == null)
			return result;
		
		//只要不指定更新ID就是全部的設定
		if(updateIDs == null){
			for(CommonSettingType type : CommonSettingType.values()){
				//對所有updateID
				for(Integer updateID : type.getUpdateID()){
					Object setting = commonSettings.getSetting(type, updateID);
					if(setting != null){
						result.put(updateID, String.valueOf(setting));
					}
				}
			}
		}
		else{
			for(CommonSettingType type : CommonSettingType.values()){
				//對傳入的updateID
				for(Integer updateID : updateIDs){
					Object setting = commonSettings.getSetting(type, updateID);
					if(setting != null){
						result.put(updateID, String.valueOf(setting));
					}
				}
			}
		}
		
		return result;
	}
	
	/**
	 * 把共用設定轉給平台使用的內容<br>
	 * 只將平台需要的資訊轉給他
	 */
	@SuppressWarnings("unchecked")
	public Object convertToWebInfo(){
		JSONObject jsonObject = new JSONObject();
		
		//虛寶交易設定
		if(this.getSendGiftSetting() != null){
			jsonObject.put("send_gift_fee", this.getSendGiftSetting().getFee());
			jsonObject.put("send_gift_minLV", this.getSendGiftSetting().getLimitMinLevel());
			jsonObject.put("send_gift_minMoney", this.getSendGiftSetting().getLimitMinMoney());
		}
		return jsonObject;
	}
	
	
	//==================getter & setter======================
	public CommonSendGiftSetting getSendGiftSetting() {
		return sendGiftSetting;
	}

	public void setSendGiftSetting(CommonSendGiftSetting sendGiftSetting) {
		this.sendGiftSetting = sendGiftSetting;
	}

	public CommonDoubleNameSetting getDoubleNameSetting() {
		return doubleNameSetting;
	}

	public void setDoubleNameSetting(CommonDoubleNameSetting doubleNameSetting) {
		this.doubleNameSetting = doubleNameSetting;
	}

	public CommonAccountLoginBlockIPSetting getAccountLoginBlockIPSetting() {
		return accountLoginBlockIPSetting;
	}

	public void setAccountLoginBlockIPSetting(CommonAccountLoginBlockIPSetting accountLoginBlockIPSetting) {
		this.accountLoginBlockIPSetting = accountLoginBlockIPSetting;
	}

	public CommonPurchaseLimitSetting getPurchaseLimitSetting() {
		return purchaseLimitSetting;
	}

	public void setPurchaseLimitSetting(CommonPurchaseLimitSetting purchaseLimitSetting) {
		this.purchaseLimitSetting = purchaseLimitSetting;
	}

	public CommonSendItemSetting getSendItemSetting() {
		return sendItemSetting;
	}

	public void setSendItemSetting(CommonSendItemSetting sendItemSetting) {
		this.sendItemSetting = sendItemSetting;
	}
}
